package org.study.module.mysql;

import org.study.entity.ClusterInfoEntity;
import org.study.entity.ClusterModuleInfoEntity;
import org.study.module.common.ModuleCommon;
import org.study.shell.ShellBase;
import org.study.shell.ShellFile;
import org.study.shell.ShellUser;

import java.util.ArrayList;
import java.util.List;

public class MysqlInstallBuilder {

    private List<String> commands;

    public MysqlInstallBuilder() {
        commands = new ArrayList<>();
    }

    /**
     * 前置安装
     *
     * @param softPath 软件上传地址
     */
    public MysqlInstallBuilder preInstall(String softPath) {
        //#-z 是判断为空， -n判断不为空， "$"是防止变量未定义报错
        commands.add("cd " + softPath);
        commands.add("# 校验安装，应显示 libaio 版本");
        commands.add("mariadb=`rpm -qa | grep mariadb`");
        commands.add("if [ -z \"$mariadb\" ]; then");
        commands.add("    echo \"mariadb已经卸载！\"");
        commands.add("else");
        commands.add("    rpm -e  $mariadb --nodeps");
        commands.add("echo \"卸载mariadb,成功！\"");
        commands.add("fi");
        commands.add("#安装 libaio");
        commands.add("libaio=`rpm -qa | grep libaio`");
        commands.add("if [ -z \"$libaio\" ]; then");
        commands.add("   rpm -ivh libaio-*.rpm --nodeps --force   # 忽略依赖校验");
        commands.add("fi");
        commands.add("numactl=`rpm -qa | grep numactl`");
        commands.add("if [ -z \"$numactl\" ]; then");
        commands.add("   rpm -ivh numactl-*.rpm --nodeps --force   # 忽略依赖校验");
        commands.add("fi");
        return this;
    }

    /**
     * 重置root用户密码
     *
     * @param password 新密码
     */
    public MysqlInstallBuilder changeRootPassword(String password) {
        commands.add("echo \" 关闭服务\"");
        commands.add("sudo service mysqld stop");
        commands.add(ShellFile.replaceContent("s/#skip-grant-tables/skip-grant-tables/g", "/etc/my.cnf"));
        commands.add("echo \" 启动服务\"");
        commands.add("sudo service mysqld start");
        commands.add("mysql -u root <<EOF");
        commands.add("FLUSH PRIVILEGES;");
        commands.add("ALTER USER 'root'@'localhost' IDENTIFIED BY '" + password + "';");
        commands.add("FLUSH PRIVILEGES;");
        commands.add("EOF");
        commands.add("echo \" 关闭服务\"");
        commands.add("sudo service mysqld stop");
        commands.add(ShellFile.replaceContent("s/skip-grant-tables/#skip-grant-tables/g", "/etc/my.cnf"));
        commands.add("echo \" 启动服务\"");
        return this;
    }

    /**
     * 主从模式下， 主服务的/etc/my.cnf 添加的配置
     * @param id  服务器id
     */
    public MysqlInstallBuilder masterCnf(Integer id){
        commands.add("cat >> /etc/my.cnf << EOF");
        commands.add("server-id="+id);
        commands.add("log_bin=mysql-bin");
        commands.add("binlog_do_db=*");
        commands.add("expire_logs_days=7");
        commands.add("EOF");
        return this;
    }

    /**
     * 主从模式下， 从服务的/etc/my.cnf 添加的配置
     * @param id  服务id
     */
    public MysqlInstallBuilder salveCnf(Integer id){
        commands.add("cat >> /etc/my.cnf << EOF");
        commands.add("server-id="+id);
        commands.add("relay_log=mysql-relay-bin");
        commands.add("log_bin=mysql-bin");
        //复制Master binlog_do_db 设置的值
        commands.add("replicate_do_db=*");
        commands.add("EOF");
        return this;
    }

    /**
     * 主从模式下，从库配置主从同步（需替换主库IP和密码）
     *
     * @param rootPassword 主库root密码
     * @param mastIp       主库ip地址
     */
    public MysqlInstallBuilder masterToSalve(String rootPassword, String mastIp) {
        commands.add("mysql -u root -p" + rootPassword + " << EOF");
        commands.add("CHANGE MASTER TO");
        commands.add("MASTER_HOST='" + mastIp + "',");
        commands.add("MASTER_USER='root',");
        commands.add("MASTER_PASSWORD='" + rootPassword + "',");
        commands.add("MASTER_LOG_FILE='mysql-bin.000001',");
        commands.add("MASTER_LOG_POS=154;");
        commands.add("START SLAVE;");
        commands.add("EOF");
        return this;
    }

    /**
     * 采用root用户，创建用户
     *
     * @param rootPassword root的密码
     * @param user         新建用户
     * @param password     新建用户的密码
     */
    public MysqlInstallBuilder createUser(String rootPassword, String user, String password) {
        commands.add("mysql -u root -p'" + rootPassword + "'<<EOF");
        commands.add("CREATE USER '" + user + "'@'%' IDENTIFIED  WITH mysql_native_password BY '" + password + "';");
        //权限设置，*.*  第一个*是库，第二个* 是表
        commands.add("GRANT ALL PRIVILEGES ON *.* TO '" + user + "'@'%' WITH GRANT OPTION;");
        commands.add("FLUSH PRIVILEGES;");
        commands.add("EOF");
        return this;
    }

    /**
     * 根据root权限，创建数据库和用户，并设置用户只能访问当前库
     * @param rootPassword  root的密码
     * @param user  创建的用户
     * @param password 创建用户的密码
     * @param db  数据库名称
     */
    public MysqlInstallBuilder createUserAndDb(String rootPassword, String user, String password,String db) {
        commands.add("mysql -u root -p'" + rootPassword + "'<<EOF");
        commands.add("CREATE DATABASE "+db+" DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;");
        commands.add("CREATE USER '" + user + "'@'%' IDENTIFIED  WITH mysql_native_password BY '" + password + "';");
        //权限设置，*.*  第一个*是库，第二个* 是表
        commands.add("GRANT ALL PRIVILEGES ON "+db+".* TO '" + user + "'@'%' WITH GRANT OPTION;");
        commands.add("FLUSH PRIVILEGES;");
        commands.add("EOF");
        return this;
    }

    public MysqlInstallBuilder install(ClusterInfoEntity infoEntity, ClusterModuleInfoEntity moduleMode) {
        String name = "mysql";
        String installPath =  infoEntity.getInstallPath()+"/mysql";
        String dataPath = installPath + "/data";
        commands.addAll(ShellUser.addGroup(name));
        commands.addAll(ShellUser.addUser(name, name, null));
        commands.addAll(ShellFile.createPath(installPath));
        commands.addAll(ShellFile.createPath(dataPath));
        commands.addAll(ModuleCommon.installByTar(infoEntity,moduleMode));
        commands.add(ShellFile.chownPath(name, name, installPath));
        commands.add("sudo $install_path/bin/mysqld --initialize --user=" + name + " --basedir=$install_path --datadir=" + dataPath);
        commands.add("sudo cat > /etc/my.cnf << EOF");
        commands.add("[mysqld]");
        commands.add("basedir=$install_path");
        commands.add("datadir=" + dataPath);
        commands.add("port = 3306");
        commands.add("socket=/tmp/mysql.sock");
        commands.add("bind-address=0.0.0.0");
        commands.add("log-error=" + installPath + "/mysqld.log");
        commands.add("pid-file=" + installPath + "/mysqld.pid");
        commands.add("character-set-server=utf8mb4");
        commands.add("collation-server=utf8mb4_unicode_ci");
        commands.add("#跳过密码认证");
        commands.add("skip-grant-tables");
        commands.add("[client]");
        commands.add("default-character-set=utf8mb4");
        commands.add("EOF");
        commands.add("echo \"查看/ect/my.cnf配置\"");
        commands.add("cat /etc/my.cnf");
        List<String> pros = new ArrayList<>();
        pros.add("export MYSQL_HOME=$install_path");
        pros.add("export PATH=\\$PATH:\\$MYSQL_HOME/bin");
        commands.addAll(ShellBase.addProfile(pros, "mysql_env.sh"));
        commands.add("#系统默认查找路径/usr/bin下无mysql命令链接");
        commands.addAll(ShellFile.lnExistDelete("/usr/bin/mysql", "$install_path/bin/mysql"));
        commands.add("#添加到自启动");
        commands.add("sudo cp $install_path/support-files/mysql.server /etc/init.d/mysqld");
        //因文件中存在多个basedir=，所有需要制定行替换
        commands.add(ShellFile.replaceContent("46s|basedir=|basedir=$install_path|","/etc/init.d/mysqld"));
        commands.add(ShellFile.replaceContent("47s|datadir=|datadir=" + dataPath + "|g", "/etc/init.d/mysqld"));
        commands.add("# 添加服务");
        commands.add("sudo chkconfig --add mysqld ");
        commands.add("echo \" 开机自启\"");
        commands.add("sudo chkconfig mysqld on");
        commands.add("echo \" 启动服务\"");
        commands.add("sudo service mysqld start ");
        commands.add("echo \"验证服务状态\"");
        commands.add("sudo service mysqld status ");
        commands.addAll(ShellBase.firewallAddPort(3306));
        return this;
    }

    public MysqlInstallBuilder restart(){
        commands.add("echo \" 关闭服务\"");
        commands.add("sudo service mysqld stop ");
        commands.add("echo \" 启动服务\"");
        commands.add("sudo service mysqld start ");
        return this;
    }


    public List<String> toList() {
        return commands;
    }

}
